home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
music4c.sit
/
Music4C Folder
/
Sources Folder
/
gen.c
< prev
next >
Wrap
Text File
|
1990-09-08
|
13KB
|
652 lines
/*
* ⌐ Graeme Gerrard 1990
* Faculty of Music, University of Melbourne
* Parkville Victoria 3052 Australia.
*
* ARPANET: grae@murdu.ucs.unimelb.edu.au
* telephone: (613) 344 4127, Fax: (613) 344 5346
*/
#include "Music4C.h"
#include "Music4C_Prototype.h"
#include "ErrorAlert.h"
#include <math.h>
#define TWOPI 6.283185308
#define ADD 1
#define SUBTRACT 2
#define MULTIPLY 3
#define DIVIDE 4
#define ABS(x) ((x) >= 0.0 ? (x) : -(x))
double *F[MAXFUNCS];
Boolean defined_funcs[MAXFUNCS];
static int scale_flag;
extern OSErr theErr;
extern void init_funcs(void);
extern void free_funcs(void);
extern void gen(int, double *);
extern Str255 theMess1, theMess2;
extern write_func(int, double *);
void gen2(int, double *, double *);
void gen5(int, double *, double *);
void gen6(int, double *, double *);
void gen7(int, double *, double *);
void gen9(int, double *, double *);
void gen10(int, double *, double *);
void gen11(int, double *, double *);
void gen12(int, double *, double *);
void gen20(int, double *, double *);
void fnscl(double *, int);
void init_funcs()
{
register int i;
Boolean *bp;
for ( i = 0, bp = defined_funcs; i< MAXFUNCS; i++) {
*bp++ = FALSE;
}
}
void free_funcs()
{
register int i;
for ( i = 0; i< MAXFUNCS; i++) {
if (defined_funcs[i] ) {
DisposPtr((Ptr)F[i]);
defined_funcs[i] = FALSE;
}
}
}
void gen(npargs, p)
double *p;
int npargs;
{
register long i;
extern char aString1[256];
extern char aString2[256];
int genno;
int genraw;
int print_switch = 0;
int len;
int fno;
genraw = (int) *(p+2);
genno = genraw % 100;
scale_flag = 1;
switch( genraw - genno) {
case 0:
break;
case 100:
print_switch = 1;
break;
case 200:
scale_flag = 0;
break;
default:
sprintf(aString1, "unknown gen switch %d", (genraw - genno));
CtoPstr(aString1);
sprintf(aString2, "for function no. %d", (int) *p);
CtoPstr(aString2);
PstringCopy((char *)theMess1, (char *)aString1);
PstringCopy((char *)theMess2, (char *)aString2);
OSError(theMess1, theMess2, NIL);
}
fno = (int) *p;
len = *(p+3);
if (defined_funcs[ (int) *p] ) {
/* i.e. already defined, free space and redefine it if different size */
if (len == (int)*F[fno])
/* same size, do nothing */
;
else { /* different size */
DisposPtr((Ptr)F[fno]);
/* reset this, so that func gets redefined in next code block */
defined_funcs[fno] = FALSE;
}
}
if ( !defined_funcs[fno] ) {
defined_funcs[fno] = TRUE;
F[fno] = (double *) NewPtr( (len+1) * sizeof(double));
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating memory in gen");
OSError(theMess1, NIL, NIL);
}
*F[fno] = (double)len;
for ( i = 1; i < len+1; i ++ )
*(F[fno]+i) = 0.0;
}
switch( ABS(genno) ) {
case 2:
if ( len != 512 ) {
PstringCopy((char *)theMess1, "\pFunctions generated by gen2 must be 512 long");
OSError(theMess1, NIL, NIL);
}
gen2(npargs, p, F[fno]);
break;
case 5:
gen5(npargs, p, F[fno]);
break;
case 7:
gen7(npargs, p, F[fno]);
break;
case 9:
gen9(npargs, p, F[fno]);
break;
case 11:
gen11(npargs, p, F[fno]);
break;
case 12:
gen12(npargs, p, F[fno]);
break;
case 20:
gen20(npargs, p, F[fno]);
break;
default:
sprintf((char *)aString1, "Error generating function number %d", fno );
CtoPstr((char *)aString1);
sprintf((char *)aString2, "gen function %d unknown", genno);
CtoPstr((char *)aString2);
PstringCopy((char *)theMess1, (char *)aString1);
PstringCopy((char *)theMess2, (char *)aString2);
OSError(theMess1, theMess2, NIL);
}
if ( print_switch )
write_func(fno, F[fno] );
}
void gen2(npargs, p, f)
double *p, *f;
int npargs;
{
register long i;
register long k;
register long j;
register long l;
register long lv;
register long lj;
int incr;
double z;
double xint;
z = p[2] - (int)p[2];
p[2] = p[2] - z;
if ( z <= 0.0 ) {
gen6(npargs, p, f);
if ( p[2] < 0.0 ) {
incr = 2;
for ( i = 2; i <= 512; i += 2 ) *(f+i) = 0.0;
k = 1;
for ( l = 2; l <=171; l++ ) {
k += 2;
if ( *(f+k) != 0.0 ) {
*(f+l) = *(f+k);
*(f+k) = 0.0;
}
else {
lv = l - 1;
goto L40;
}
}
for ( i = 171; i <= 512; i += incr ) *(f+i) = 0.0;
}
}
else {
/* change order of p args */
for ( l = npargs; l > 1; l-- )
p[l] = p[l-1];
gen5(npargs+1, p, f);
xint = 100.0 / 12.0 * z;
incr = 1;
for ( l = 2; l <=171; l++ ) {
if ( *(f+l) == 0.0 ) {
lv = l - 1;
goto L40;
}
}
for ( l = 171; i <= 512; l += incr ) *(f+l) = 0.0;
lv = 170;
}
L40:
lj = 3 * lv - 1;
for ( i = 2; i <= lj; i += 3 ) {
j = lj + 2 - i;
*(f+j) = *(f+lv);
lv--;
if ( z <= 0.0 )
*(f+j-1) = 1 + lv * incr;
else
*(f+j-1) = ((int)( 128.0 * pow(2.0, (lv*xint)) )) / 128.0;
*(f+j+1) = 0.0;
}
}
void gen5(npargs, p, f)
double *p, *f;
int npargs;
{
register int i;
int len = *f;
int j, k, l, m, n;
double x1, y1, x2, y2;
double c;
y2 = *(p+5);
i = 1;
n = 6;
while (n < npargs) {
if ( *(p+n+1) <= 0.0 )
break;
y1 = y2;
y2 = *(p+n+1);
j = i;
if ( j > len )
break;
*(f+j) = y1;
m = j + 1;
i = *(p+n);
j = i - j;
if ( m <= i ) {
c = pow( (y2/y1), (1.0/j));
/* c = pow( (y2/y1), (1.0/(*(p+n))));*/
for ( l = m; l < i; l++ )
*(f+l) = *(f+l-1) * c;
}
n += 2;
}
*(f+i) = y2;
fnscl(f, len);
}
void gen6(npargs, p, f)
double *p, *f;
int npargs;
{
register long i;
register long k;
register long l;
register long j;
int len;
double xj;
double vratio;
double amp1;
double amp2;
double base;
len = (int)*f;
for ( i = 1; i < len+1; i++ ) *(f+i) = 0.0;
i = 0;
amp2 = p[4];
for ( k = 5; k < npargs; k += 2 ) {
if ( p[k] > 0.0 ) {
amp1 = amp2;
amp2 = p[k+1];
j = i + 1;
i = j + p[k] - 1;
xj = j;
vratio = amp2 / amp1;
base = log( (i+1) / xj );
for ( l = j; l <= i; l++ ) {
if ( l <= len )
*(f+l) = amp1 * pow(vratio, (log(l/xj) / base));
else
break;
}
}
else
break;
}
fnscl(f, len);
}
void gen7(npargs, p, f)
double *p, *f;
int npargs;
{
/* straight line segments */
/* p4 = 1st x value
p5 = 1st y value
p6 = 2nd x value
p7 = 2nd y value
etc.
*/
register int i;
register int n;
int len = *f;
int j, k;
double x1, y1, x2, y2;
double x_diff, y_diff;
y2 = *(p+5);
x2 = *(p+4);
n = 6;
while (n < npargs) {
x1 = x2;
x2 = *(p+n);
y1 = y2;
y2 = *(p+n+1);
y_diff = y2 - y1;
x_diff = x2 - x1;
j = (int)x1;
if ( j < 1 )
j = 1;
k = (int)x2;
for ( i = j; i<=k; i++)
*(f+i) = y1 + (y_diff *((i - x1)/x_diff));
n += 2;
}
*(f+(int)x2) = y2;
if ( scale_flag )
fnscl(f, len);
}
void gen9(npargs, p, f)
double *p, *f;
int npargs;
{
/*
*(p+4) = partial no, *(p+5) = amplitude, *(p+6) = phase in degrees
*/
register int i;
register int n;
int len = *f;
double arg;
double rads;
double hno;
double amp;
double phs;
rads = TWOPI/len;
for ( n = 4; n < npargs; n += 3 ) {
hno = *(p+n);
amp = *(p+n+1);
phs = (*(p+n+2) * len) / 360.0;
if ( hno == 0.0 )
break;
for ( i = 1; i < len+1; i++ ) {
*(f+i) += (amp * sin(rads * ((i-1) * hno + phs)));
}
}
fnscl(f, len);
}
void gen10(npargs, p, f)
double *p, *f;
int npargs;
{
/*
*(p+4) = amp of harmonic no 1,
*(p+5) = amp of harmonic no 2,
*(p+6) = amp of harmonic no 3, etc.
*/
register int i;
register int n;
int len = *f;
double arg;
double rads;
double hno;
double amp;
rads = TWOPI/len;
for ( n = 4; n < npargs; n += 3 ) {
hno = n-3;
amp = *(p+n+1);
if ( hno == 0.0 )
break;
for ( i = 1; i < len+1; i++ )
*(f+i) += (amp * sin(rads * ((i-1) * hno)));
}
fnscl(f, len);
}
void gen11(npargs, p, f)
double *p, *f;
int npargs;
{
/* just copies arguments into F */
register int i;
register int n;
int len = *f;
n = 4;
for ( i = 1; i < len+1; i++ ) {
*(f+i) = *(p+n);
n++;
}
if ( scale_flag )
fnscl(f, len);
}
void gen12(npargs, p, f)
double *p, *f;
int npargs;
{
/* combines two functions */
/* *(p+4) = first function no
*(p+5) = start location in first function
*(p+6) = end location in first function
*(p+7) = second function no.
if positive with no fractional part = add the two functions.
if negative with no fractional part = subtract this function
from the first function.
if positive with fractional part = multiply the two functions.
if negative with fractional part = divide the first function
by the second function.
*(p+8) = start location in second function
*(p+9) = end location in second function
*/
register int i;
int len = *f;
int fno1, fno2;
int len1, len2;
int start1, end1, start2, end2;
int theOp;
/* get function numbers */
fno1 = ABS(*(p+4));
fno2 = ABS(*(p+7));
/* check they are both defined */
if ( !defined_funcs[fno1]) {
sprintf(aString1, "Attempt to access undefined function %d in gen12", fno1);
CtoPstr(aString1);
sprintf(aString2, "function no. %d", (int) *p);
CtoPstr(aString2);
PstringCopy((char *)theMess1, (char *)aString1);
PstringCopy((char *)theMess2, (char *)aString2);
OSError(theMess1, theMess2, NIL);
}
if ( !defined_funcs[fno2]) {
sprintf(aString1, "Attempt to access undefined function %d in gen12", fno2);
CtoPstr(aString1);
sprintf(aString2, "function no. %d", (int) *p);
CtoPstr(aString2);
PstringCopy((char *)theMess1, (char *)aString1);
PstringCopy((char *)theMess2, (char *)aString2);
OSError(theMess1, theMess2, NIL);
}
/* get here if both functions are defined, figure out operation */
if ( *(p+7) > 0.0) {
if ( (*(p+7) - (int)*(p+7)) == 0.0 )
theOp = ADD;
else
theOp = MULTIPLY;
}
else if ( *(p+7) < 0.0) {
if ( (*(p+7) - (int)*(p+7)) == 0.0 )
theOp = SUBTRACT;
else
theOp = DIVIDE;
}
/* get start and end bounds */
start1 = (int)*(p+5);
end1 = (int)*(p+6);
start2 = (int)*(p+8);
end2 = (int)*(p+9);
if ( start1 > *F[fno1] || start1 < 1) {
sprintf(aString1, "gen12, bad start location %d in first function", start1);
CtoPstr(aString1);
PstringCopy((char *)theMess1, (char *)aString1);
OSError(theMess1, NIL, NIL);
}
if ( end1 > *F[fno1] || end1 < 1) {
sprintf(aString1, "gen12, bad end location %d in first function", end1);
CtoPstr(aString1);
PstringCopy((char *)theMess1, (char *)aString1);
OSError(theMess1, NIL, NIL);
}
if ( start2 > *F[fno2] || start2 < 1) {
sprintf(aString1, "gen12, bad start location %d in second function", start2);
CtoPstr(aString1);
PstringCopy((char *)theMess1, (char *)aString1);
OSError(theMess1, NIL, NIL);
}
if ( start2 > *F[fno2] || end2 < 1) {
sprintf(aString1, "gen12, bad end location %d in second function", end2);
CtoPstr(aString1);
PstringCopy((char *)theMess1, (char *)aString1);
OSError(theMess1, NIL, NIL);
}
/* assume that lengths are the same, we'll add expansion and contraction later */
for ( i = start1; i <= end1; i++ ) {
switch (theOp ) {
case ADD:
*(f+i) = *(F[fno1]+i) + *(F[fno2]+i);
break;
case SUBTRACT:
*(f+i) = *(F[fno1]+i) - *(F[fno2]+i);
break;
case MULTIPLY:
*(f+i) = *(F[fno1]+i) * *(F[fno2]+i);
break;
case DIVIDE:
if (*(F[fno2]+i) != 0.0 )
*(f+i) = *(F[fno1]+i) - *(F[fno2]+i);
else
*(f+i) = *(F[fno1]+i);
break;
}
}
if ( scale_flag )
fnscl(f, len);
}
void gen20(npargs, p, f)
double *p, *f;
int npargs;
{
/* reads in a file of floating point values */
register i;
int len = *f;
SFReply reply;
SFTypeList types;
Point where;
float *theFloats;
int theRefNum;
long count;
SetPt(&where, 100, 100);
SFGetFile(where, NIL, NIL, -1, NIL, NIL, &reply);
if(!reply.good) {
return;
}
count = (float)len * sizeof(float);
theFloats = (float *) NewPtr(sizeof(float) * len);
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating memory in gen20");
OSError(theMess1, NIL, NIL);
}
theErr = FSOpen(reply.fName, reply.vRefNum, &theRefNum);
theErr = FSRead(theRefNum, &count, theFloats);
theErr = FSClose(theRefNum);
if ( theErr != noErr ) {
DisposPtr((Ptr)theFloats);
return;
}
len = (count/sizeof(long));
for ( i = 1; i < len+1; i++ )
*(f+i) = (double)theFloats[i-1];
if ( scale_flag )
fnscl(f, len);
DisposPtr((Ptr)theFloats);
}
write_func(fno, f)
double *f;
int fno;
{
extern char theMessage[MAXSTRING];
extern int out3_flag;
register int i;
int len = *f;
if ( out3_flag ) {
sprintf((char *)theMess1, "Function no. %d length is %d", fno, len );
Report((char *)theMess1);
for ( i = 1; i < len+1; i++ ) {
sprintf((char *)theMess1, "%d %f\n", i, *(f+i) );
Report((char *)theMess1);
}
Report("-----------------------------------\n");
}
}
void fnscl(f, len)
double *f;
int len;
{
register int i;
double wmax,xmax = 0;
for(i = 1; i < len+1; i++ ) {
if ((wmax = fabs(*(f+i))) > xmax) xmax = wmax;
}
for(i = 1; i < len+1; i++ ) {
*(f+i) /= xmax;
}
}
/*-------------------------------------------------------------------------------*/